/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package business;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;

/**
 * XmlHandler pro SAX pro pocasi z yr.no, pro pochopeni funkcnosti je dobre
 * prohlednout si strukturu xml souboru, ktery posila yr.no(http://api.yr.no/weatherapi/locationforecast/1.8/)
 * @author stana
 */
public class YRXmlHandler implements ContentHandler{

    //do forecast se ukladaji data z xml dokumentu
    private YRWeatherForecast forecast=new YRWeatherForecast();
    private YRDay actualDay;
    private YrHour actualHour;


    /* tenhle enum je kvuli rozlisovani tagu time, aktualni hodnoty jsou ulozeny
       v promene timeType(pozn. pro pochopeni problematiky je nutne znat strukturu
         xml souboru)*/
    private enum TimeType{equalsDate,firstAfterEquals,nextAfterEquals};
    private TimeType timeType;

    public void setDocumentLocator(Locator locator)
    {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void startDocument() throws SAXException
    {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void endDocument() throws SAXException
    {
        if(!actualDay.isEmpty())
        {
            forecast.addDay(actualDay.getDate(), actualDay);
        }


        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void startPrefixMapping(String prefix, String uri) throws SAXException
    {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void endPrefixMapping(String prefix) throws SAXException
    {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException
    {

        if(localName.equals("time"))
        {
            String from=atts.getValue("from");
            String to=atts.getValue("to");

            if(from.equals(to)) /*datum a cas z atributu from a to se rovnaji,
                                    v teto situaci nasleduji tagy jako je
                                    smer vetru atd.,ale nejsou uvedene srazky*/
            {
                timeType=TimeType.equalsDate;
                Integer hour=Integer.valueOf(from.substring(11, 13));
                String date=from.substring(0, 10);//vezme z atributu from datum,
                if(actualDay==null)
                {
                    actualDay=new YRDay(date);
                }
                if(hour==0) /*v xml je dalsi den, takze stavajici den ulozim a
                                vytvori se novy den s aktualnim datumem*/
                {
                    if(actualDay!=null)//kdyz actualDay neni null(na zacatku dokumentu),
                    {                   //tak vlozi actualDay do forecast
                        forecast.addDay(actualDay.getDate(), actualDay);
                    }
                    actualDay=new YRDay(date);
                }

                actualHour=new YrHour(hour);
            }

        }
        else if(localName.equals("precipitation")) //tag zaznamenavajici srazky
        {
            if(timeType==TimeType.firstAfterEquals)/*zaznam se vlozi jen pokud je
                      tento tag v tagu time, ktery nasleduje primo za tagy jako
                      je windSpeed atd.*/
            {
                actualHour.setPrecipitation(Double.valueOf(atts.getValue("value")));
            }

        }
        else if(localName.equals("windDirection"))
        {
            actualHour.setWindDirection(atts.getValue("name"));
        }
        else if(localName.equals("windSpeed"))
        {
            actualHour.setWindSpeed(Double.valueOf(atts.getValue("mps")));
        }
        else if(localName.equals("temperature"))
        {
            actualHour.setTemperature(Double.valueOf(atts.getValue("value")));
        }
        else if(localName.equals("pressure"))
        {
            actualHour.setPressure(Double.valueOf(atts.getValue("value")));
        }

        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void endElement(String uri, String localName, String qName) throws SAXException
    {
        if(localName.equals("time"))//ukoncovaci tag time
        {
            if(timeType==TimeType.equalsDate)//po TimeType.equalDate
            {                                //nasleduje typ firstAfterEquals
                timeType=TimeType.firstAfterEquals;
            }

            /*zavira se druhy typ tagu cas, takze se muze zaznam o pocasi vlozit
             do promene actualDay*/
            else if(timeType==TimeType.firstAfterEquals)
            {
                timeType=TimeType.nextAfterEquals;
//                if(actualHour.getHour()==0)//predpoved pro dalsi den
//                {
//                    actualDay=new YRDay(actualDay.getDate());
//                }
                //System.out.println("actualDay"+actualDay.getDate()+"add hour: "+actualHour.getHour());
                actualDay.addHour(actualHour.getHour(), actualHour);

            }
        }
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void characters(char[] ch, int start, int length) throws SAXException
    {
       // throw new UnsupportedOperationException("Not supported yet.");
    }

    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
    {
       // throw new UnsupportedOperationException("Not supported yet.");
    }

    public void processingInstruction(String target, String data) throws SAXException
    {
       // throw new UnsupportedOperationException("Not supported yet.");
    }

    public void skippedEntity(String name) throws SAXException
    {
       // throw new UnsupportedOperationException("Not supported yet.");
    }


    /**
     * vrati predpoved pocasi, coz reprezentuje trida YRWeatherForecast, document se nejdrive
     * musi naparsovat, az pak se pouzije tato metoda
     * @return forecast
     */
    public YRWeatherForecast getForecast()
    {
        return forecast;
    }

}